#ifndef __DISTCAPPROTO_H__
#define __DISTCAPPROTO_H__

#include "GAframework.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "CaP_Validator.hpp"

using namespace std;

class DistCaPProtocolException : public EHW_Exception
{
    public:
    DistCaPProtocolException(char *mess) : EHW_Exception(mess) {};
};

enum Packet_Type
{
	PK_TYPE_CONFIRM,
	PK_TYPE_EVAL,
	PK_TYPE_PARM_REQ,
	PK_TYPE_PARM_VAL,
	PK_TYPE_END
};

/*typedef struct
{
	unsigned int rows, cols, lb, n_ing, n_op;
} handshake_header;
*/

typedef struct
{
	unsigned int	n_eval;
	unsigned int	simSteps;
	float			minStartAngle, maxStartAngle;
} handshake_header;

typedef struct
{
	Packet_Type P_Type;	//!< Tipo di pacchetto
	union
	{
		int		IntPayload;
		float	FloatPayload;
	} payload;
} StandardPacket;

class DistCaPProtocol
{

	public:
	int my_socket;
	DistCaPProtocol(int sck) throw(DistCaPProtocolException);
	//DistCaPProtocol(string &IP,int PORT) throw(DistCaPProtocolException);

	int startHandshake(unsigned int n_eval, unsigned int simSteps, float minStartAngle, float maxStartAngle) throw(DistCaPProtocolException);
	int waitHandshake(GAmodSettings &settings) throw(DistCaPProtocolException);

	void waitPacket(StandardPacket &pckt) throw(DistCaPProtocolException);
	void sendPacket(StandardPacket &pckt) throw(DistCaPProtocolException);
	void sendConfirm(int val) throw(DistCaPProtocolException);
	int  waitConfirm() throw(DistCaPProtocolException);

	void sendEvals(Popolazione *pop) throw(DistCaPProtocolException);
	void getEvals(Popolazione *pop, int from, int to) throw(DistCaPProtocolException);

	int startShutdown() throw(DistCaPProtocolException);
};

#endif
